# tipc(8) completion                                       -*- shell-script -*-

_tipc_media()
{
    local optind=$1

    if ((cword == optind)); then
        COMPREPLY=($(compgen -W 'media' -- $cur))
        return 0
    elif ((cword == optind + 1)); then
        COMPREPLY=($(compgen -W 'udp eth ib' -- $cur))
        return 0
    fi

    return 1
}

_tipc_bearer()
{
    local optind=$1
    local media i

    if _tipc_media $optind; then
        return
    fi

    for ((i = 0; i < cword; i++)); do
        if [[ ${words[i]} == 'media' ]]; then
            media=${words[i + 1]}
        fi
    done

    if ((cword == optind + 2)); then
        case "$media" in
            "udp")
                COMPREPLY=($(compgen -W 'name' -- $cur))
                ;;
            "eth" | "ib")
                COMPREPLY=($(compgen -W 'device' -- $cur))
                ;;
        esac
    elif ((cword == optind + 3)); then
        case "$media" in
            "udp")
                local names=$(
                    tipc bearer list 2>/dev/null | awk -F: '/^udp:/ {print $2}'
                )
                COMPREPLY=($(compgen -W '$names' -- $cur))
                ;;
            "eth")
                local interfaces=$(command ls /sys/class/net/)
                COMPREPLY=($(compgen -W '$interfaces' -- $cur))
                ;;
        esac
    fi
}

_tipc_link_opts()
{
    COMPREPLY=($(compgen -W 'priority tolerance window' -- $cur))
}

_tipc_link()
{
    local optind=$1
    local filter=$2

    if ((cword == optind)); then
        COMPREPLY=($(compgen -W 'link' -- $cur))
    elif ((cword == optind + 1)); then
        # awk drops link state and last trailing :
        local links=$(tipc link list 2>/dev/null |
            awk '{print substr($1, 0, length($1))}')
        local -a exclude
        [[ $filter == peers ]] && exclude=(-X broadcast-link)
        COMPREPLY=($(compgen "${exclude[@]}" -W '$links' -- $cur))
    fi
}

_tipc()
{
    local cur prev words cword optind i p
    _init_completion || return

    optind=1
    COMPREPLY=()

    # Flags can be placed anywhere in the commandline
    case "$cur" in
        -*)
            COMPREPLY=($(compgen -W '-h --help' -- $cur))
            return
            ;;
    esac

    if ((cword == 1)); then
        COMPREPLY=($(
            compgen -W 'bearer link media nametable node socket' -- $cur
        ))
        return
    fi

    case "${words[optind]}" in
        bearer)
            ((optind++))

            if ((cword == optind)); then
                COMPREPLY=($(compgen -W 'enable disable set get list' -- $cur))
                return
            fi

            case "${words[optind]}" in
                enable)
                    local media params
                    ((optind++))

                    if ((cword < optind + 4)); then
                        _tipc_bearer $optind
                        return
                    fi

                    for ((i = 0; i < cword; i++)); do
                        if [[ ${words[i]} == 'media' ]]; then
                            media=${words[i + 1]}
                        fi
                    done
                    case "$media" in
                        "udp")
                            declare -a params=("localip" "localport" "remoteip"
                                "remoteport" "domain" "priority")
                            ;;
                        "eth" | "ib")
                            declare -a params=("domain" "priority")
                            ;;
                        *)
                            return
                            ;;
                    esac

                    # If the previous word was a known parameter, we assume a
                    # value for that key. Note that this would break if the
                    # user attempts to use a known key as value.
                    for i in "${params[@]}"; do
                        if [[ $prev == "$i" ]]; then
                            return
                        fi
                    done

                    # In order not to print already used options, we remove them
                    for p in "${words[@]}"; do
                        for i in "${params[@]}"; do
                            if [[ $p == "$i" ]]; then
                                params=("${params[@]/$i/}")
                            fi
                        done
                    done

                    COMPREPLY=($(compgen -W '${params[@]}' -- $cur))
                    ;;
                disable)
                    ((optind++))

                    _tipc_bearer $optind
                    ;;
                get)
                    ((optind++))

                    if ((cword == optind)); then
                        _tipc_link_opts
                    elif ((cword >= optind + 1)); then
                        _tipc_bearer $((optind + 1))
                    fi
                    ;;
                set)
                    ((optind++))

                    if ((cword == optind)); then
                        _tipc_link_opts
                    elif ((cword >= optind + 2)); then
                        _tipc_bearer $((optind + 2))
                    fi
                    ;;
            esac
            ;;
        link)
            ((optind++))

            if ((cword == optind)); then
                COMPREPLY=($(compgen -W 'get set list statistics' -- $cur))
                return
            fi

            case "${words[optind]}" in
                get)
                    ((optind++))

                    if ((cword == optind)); then
                        _tipc_link_opts
                    elif ((cword >= optind + 1)); then
                        _tipc_link $((optind + 1)) "peers"
                    fi
                    ;;
                set)
                    ((optind++))

                    if ((cword == optind)); then
                        _tipc_link_opts
                    elif ((cword >= optind + 2)); then
                        _tipc_link $((optind + 2)) "peers"
                    fi
                    ;;
                statistics)
                    ((optind++))

                    if ((cword == optind)); then
                        COMPREPLY=($(compgen -W 'show reset' -- $cur))
                        return
                    fi

                    case "${words[optind]}" in
                        show | reset)
                            _tipc_link $((optind + 1))
                            ;;
                    esac
                    ;;
            esac
            ;;
        media)
            ((optind++))

            if ((cword == optind)); then
                COMPREPLY=($(compgen -W 'get set list' -- $cur))
                return
            fi

            case "${words[optind]}" in
                get)
                    ((optind++))

                    if ((cword == optind)); then
                        _tipc_link_opts
                    elif ((cword >= optind + 1)); then
                        _tipc_media $((optind + 1))
                    fi
                    ;;
                set)
                    ((optind++))

                    if ((cword == optind)); then
                        _tipc_link_opts
                    elif ((cword >= optind + 2)); then
                        _tipc_media $((optind + 2))
                    fi
                    ;;
            esac
            ;;
        nametable)
            ((optind++))

            if ((cword == optind)); then
                COMPREPLY=($(compgen -W 'show' -- $cur))
            fi
            ;;
        node)
            ((optind++))

            if ((cword == optind)); then
                COMPREPLY=($(compgen -W 'list get set' -- $cur))
                return
            fi

            case "${words[optind]}" in
                get | set)
                    ((optind++))

                    if ((cword == optind)); then
                        COMPREPLY=($(compgen -W 'address netid' -- $cur))
                    fi
                    ;;
            esac
            ;;
        socket)
            ((optind++))

            if ((cword == optind)); then
                COMPREPLY=($(compgen -W 'list' -- $cur))
            fi
            ;;
    esac
} &&
    complete -F _tipc tipc

# ex: filetype=sh
